package org.itboys.store.tools;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.httpclient.HttpStatus;
import org.itboys.commons.CommonConstants;
import org.itboys.commons.utils.json.JsonUtils;
import org.itboys.commons.utils.time.TimeUtils;
import org.itboys.store.entity.Product;
import org.itboys.weixin.tools.HttpHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import weibo4j.org.json.JSONArray;
import weibo4j.org.json.JSONObject;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.util.*;

/**
 * Created by huml on 2016/5/9.
 * 云商接口工具类
 */
public class CloudBuilderInteface {

    private static Logger logger = LoggerFactory.getLogger(CloudBuilderInteface.class);

    private final static String TEST_URL = "http://192.168.0.15:9052/api/";//沙箱环境http网关 后面加上具体的接口名称
//    private final static String TEST_URL = "http://114.215.241.177:9051/api/";//沙箱环境http网关 后面加上具体的接口名称
    private final static String APP_KEY = "7206ae11b1c040439a84f2852289b919e7a4286f6a7b478f758b2aa08f12c762";//云商分配给应用的AppKey
    private final static String SECERT_KEY = "1f62d86ca8da421a842e4f32471aa0f907fdc07d39c34c139bd43b6c415ae462";//云商提供的secretKey
    private final static String V = "1.0";//API协议版本
    private final static String SIGN_METHOD = "md5";//参数加密方法
    private final static Long BUCODE = 1L;//微盟编码

    public final static Integer QUERY_TYPE_SIMPLE = 1;//获取简要商品信息
    public final static Integer QUERY_TYPE_DETAIL = 0;//获取详细商品信息

    public final static Integer QUERY_ORDER_STATUS_FAIL = 0;//订单同步失败
    public final static Integer QUERY_ORDER_STATUS_SUCCESS = 1;//订单同步成功
    public final static Integer QUERY_ORDER_STATUS_PAY_SUCCESS = 2;//支付成功
    public final static Integer QUERY_ORDER_STATUS_PAY_FAIL = 3;//支付失败
    public final static Integer QUERY_ORDER_STATUS_SEND_SUCCESS = 4;//已发货
    public final static Integer QUERY_ORDER_STATUS_TRADE_SUCCESS = 5;//交易成功
    public final static Integer QUERY_ORDER_STATUS_TRADE_FAIL = 6;//交易失败(用户支付后不能发货)
    public final static Integer QUERY_ORDER_STATUS_CLOSE = 7;//订单关闭
    public final static Integer QUERY_ORDER_STATUS_REFUND_SUCCESS = 8;//退款成功
    public final static Integer QUERY_ORDER_STATUS_REFUND_FAIL = 9;//退款失败


    /**
     * 获得微盟下所有商品的id
     * @throws Exception
     */
    public static List<Product> queryAllGoodsId(Integer queryType) throws Exception{
        Map<String, Object> param = Maps.newHashMap();
        param.put("bucode", BUCODE);//微盟编码
        param = createSign(param);
        String result = HttpHelper.doPostWithUtf8(TEST_URL + "goods/QueryAllGoodsId", param);
        JSONObject object = new JSONObject(result);
        logger.info("********goods/QueryAllGoodsId*****result*****" + result);
        Integer recCode = (Integer)object.get("recCode");//接口返回的状态码
        if(recCode.equals(HttpStatus.SC_OK)){
            JSONArray goodInfos = (JSONArray) object.get("goodInfos");
            List<Product> list = Lists.newArrayListWithExpectedSize(goodInfos.length());
            for (int i = 0 ; i < goodInfos.length() ; i ++) {
                Product product = queryGoodsInfoDetailById((String)goodInfos.get(i), queryType);
                list.add(product);
            }
            return list;
        } else {
            throw new RuntimeException("**********同步产品id集合异常***********recCode:"+recCode);
        }
    }

    /**
     * 根据skuId获取产品的全部信息
     * @param skuId
     * @throws Exception
     */
    public static Product queryGoodsInfoDetailById(String skuId, Integer queryType) throws Exception{
        Map<String, Object> param = Maps.newHashMap();
        param.put("bucode", BUCODE);//微盟编码
        param.put("skuId", skuId);
        param.put("queryType", queryType);
        param = createSign(param);
        String result = HttpHelper.doPostWithUtf8(TEST_URL + "goods/QueryGoodsInfoById", param);
        logger.info("********goods/QueryGoodsInfoById*****result*****" + result);
        JSONObject object = new JSONObject(result);
        Integer recCode = (Integer)object.get("recCode");//接口返回的状态码
        if(recCode.equals(HttpStatus.SC_OK)){
            Map<String, Object> productMap = JsonUtils.jsonToObject(Map.class, object.getString("goodInfos"));
            Product product = mapToObject(productMap, Product.class);
            return product;
        } else {
            throw new RuntimeException("**********同步产品详细信息异常*****skuId*******"+skuId+"******recCode:"+recCode);
        }
    }

    /**
     * 微盟确认订单
     * @param thirdPartOrderId
     * @param orderItemList
     * @param userInfo
     * @return  -100参数错误  200订单可以生成  201需要拆单  -998库存不足  -999产生关税  -102没有库存
     * @throws Exception
     */
    public static Integer orderInfoConfirmation(String thirdPartOrderId, String orderItemList, String userInfo) throws Exception{
        Map<String, Object> param = Maps.newHashMap();
        param.put("bucode", BUCODE);//微盟编码
        param.put("thirdPartOrderId", thirdPartOrderId);
        param.put("orderItemList", orderItemList);
        param.put("userInfo", userInfo);
        param = createSign(param);
        System.out.println(param.toString());
        String result = HttpHelper.doPostWithUtf8(TEST_URL + "Order/OrderInfoConfirmation", param);
        logger.info("********goods/OrderInfoConfirmation*****result*****" + result);
        JSONObject object = new JSONObject(result);
        Integer recCode = (Integer)object.get("recCode");//接口返回的状态码
        return recCode;
    }

    /**
     * 微盟下单
     * @param thirdPartOrderId
     * @param orderItemList
     * @param userInfo
     * @return  -100参数错误  -101商品信息错误  -102没有库存  -103请求过于频繁  -104虚拟商品不存在  -105用户地址错误  -2或-21支付失败  -200其他错误
     * @throws Exception
     */
    public static Integer bookorder(String thirdPartOrderId, String orderItemList, String userInfo) throws Exception{
        Map<String, Object> param = Maps.newHashMap();
        param.put("bucode", BUCODE);//微盟编码
        param.put("thirdPartOrderId", thirdPartOrderId);
        param.put("orderItemList", orderItemList);
        param.put("userInfo", userInfo);
        param = createSign(param);
        String result = HttpHelper.doPostWithUtf8(TEST_URL + "Order/bookorder", param);
        logger.info("********goods/bookorder******param*****"+param.toString());
        logger.info("********goods/bookorder******result*****" + result);
        JSONObject object = new JSONObject(result);
        Integer recCode = (Integer)object.get("recCode");//接口返回的状态码
        return recCode;
    }

    /**
     * 同步订单状态
     * @param thirdPartOrderId
     * @return
     * @throws Exception
     */
    public static JSONObject queryOrderInfo(String thirdPartOrderId) throws Exception{
        Map<String, Object> param = Maps.newHashMap();
        param.put("bucode", BUCODE);
        param.put("thirdPartOrderId", thirdPartOrderId);
        param = createSign(param);
        String result = HttpHelper.doPostWithUtf8(TEST_URL + "Order/queryOrderInfo", param);
        logger.info("********goods/queryOrderInfo******param*****"+param.toString()+"******result*****" + result);
        JSONObject object = new JSONObject(result);
        return object;
    }

    /**
     * 参数签名  返回完整的参数map
     * @param param
     * @return
     */
    public static Map<String, Object> createSign(Map<String, Object> param){
        param.put("sign_method", SIGN_METHOD);
        param.put("timestamp", TimeUtils.format(new Date(), CommonConstants.DATE.FORMAT_DEFAULT));
        param.put("app_key", APP_KEY);
        param.put("v", V);
        List<String> keys = new ArrayList<String>(param.keySet());
        Collections.sort(keys);

        String prestr = "";//排序后的字符串
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = String.valueOf( param.get(key) );
            prestr = prestr + key + value ;
        }
        prestr = SECERT_KEY + prestr + SECERT_KEY;
        System.out.println(prestr);
        prestr = DigestUtils.md5Hex(prestr.getBytes());
        param.put("sign", prestr.toUpperCase());
        return param;
    }

    /**
     * 将得到的map转换成实体对象
     * @param map
     * @param beanClass
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T>T mapToObject(Map<String, Object> map, Class<T> beanClass) throws Exception {
        if (map == null)
            return null;
        T obj = beanClass.newInstance();
        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            int mod = field.getModifiers();
            if(Modifier.isStatic(mod) || Modifier.isFinal(mod)){
                continue;
            }
            String key = field.getName();
            if(key.equals("serialVersionUID") || key.equals("pricePinkage") || key.startsWith("is") || key.equals("numPinkage") || key.equals("postage")){
                continue;
            }
            String op = field.getGenericType().toString();
            if(key.equals("detail")){
                key = "Detail";
            }
            if(key.equals("imageUrl")){
                key = "IMAGE_URL";
            }
            if(key.equals("skuProperty")){
                key = "SkuProperty";
            }
            if(key.equals("goodsProperty")){
                key = "GoodsProperty";
            }
            if(key.equals("onlineStatus")){
                key = "OnlineStatus";
            }
            if(key.equals("imgList")){
                key = "IMGList";
            }
            field.setAccessible(true);
            Object value = map.get(key);
            if(value == null){
                field.set(obj, value);
                continue;
            }
            if(op.equals("class java.lang.Integer")){
                field.set(obj, (Integer)value);
            } else if (op.equals("class java.lang.Double")) {
                field.set(obj, Double.valueOf(value.toString()));
            } else {
                field.set(obj, value);
            }
    }
        return obj;
    }
}
